home *** CD-ROM | disk | FTP | other *** search
- /*
- * Yamana's Otomeza Plug-in Tool
- * Pi セーバ
- *
- * 1995.08.06
- * 1995.08.27 部分セーブへの対処をあきらめた(~~~)
- * 1995.09.01 パターンチェック部のバグ除去
- *
- * 問題点
- * ・32ドット単位でしか保存できない。
- * メモリがふんだんにあるか、高速マシンであるか、多少圧縮率を犠牲にする
- * か、このうちどれかを選ばない限り無理。
- *
- * "Pi" (c) Yanagisawa
- */
-
- #include "otome_pi.h"
-
- const char longname[] = "ぱいせーば";
- const char extend[] = "PI";
-
- #define USE_FILE PI_SAVE
- #include "otome_pi.c"
-
- char def_comment[]= "PiSAVER/OTOMEZA";
-
- typedef
- struct
- { char mode; /* パレットなし= 0x80 */
- char n;
- char m; /* 縦横比 n/m */
- char pix; /* 4 or 8 */
- char name[4]; /* 機種名 */
- short mdat_len; /* 機種予約コードサイズ */
- char *mdat; /* 機種予約コード */
- short x;
- short y;
- }
- PiHeader;
-
-
- #define MAX_PIXPAGESIZE (32*1024)
- int pixPageSize= MAX_PIXPAGESIZE;
- int pixPage = 0;
-
- int Pi_countBit = 0;
- int Pi_maxBit = MAX_PIXPAGESIZE*8 ;
- char *ColTbl;
-
- int precol;
- char **pixel;
-
- char *user ='\0';
- char *comment='\0';
-
- /********************************************************************/
-
- int Pi_getColor256();
- int Pi_getColor16();
- int Pi_getColor256D();
- int Pi_getColor16D();
- void Pi_putColor256();
- void Pi_putColor16();
- void Pi_putPos();
- void Pi_putLen();
-
- int Width;
- char *f2buf;
-
- int Pi_posTable[][2] =
- { {-2, 0 }, /* 0 :前のピクセルにより変化するので注意 */
- { 0,-1 }, /* 1: 1ライン上 */
- { 0,-2 }, /* 2: 2ライン上 */
- { 1,-1 }, /* 3: 1ライン上の1ドット右 */
- {-1,-1 } /* 4: 1ライン上の1ドット左 */
- };
-
- int Pi_encode( head,image )
- PiHeader *head;
- char *image;
- {
- int i;
- int c0,c1,l[5];
- int Height,imagemax;
- int prepos,pos, off, len;
- int (*Pi_getColor)();
- void (*Pi_putColor)();
-
- /* 32ドット単位で渡される */
- Width = (head->x+31) & 0xffe0 ;
- Height = head->y ;
- imagemax = Width*Height;
-
- if( (f2buf=(char*)PI_MALLOC( Width*2+2 ))==NULL )
- return PI_ERROR_NO_MEMORY;
-
- if( head->pix == 8 )
- { Pi_getColor = Pi_getColor256D;
- Pi_putColor = Pi_putColor256;
- }else
- { Pi_getColor = Pi_getColor16D;
- Pi_putColor = Pi_putColor16;
- }
- for( i=1; i<=4 ; i++ )
- Pi_posTable[i][0] += Pi_posTable[i][1]*Width;
-
- /**************************/
-
- /* (1) 始めの2色で先頭2ラインを埋める */
- c0 = Pi_getColor( 0 );
- for ( i = 0; i<=Width ; i++ ) /* 余分に埋めるのは長さを調べるとき */
- WORD( f2buf+i*2 ) = c0; /* pos=3,4では1ドットずれているため */
-
- precol = 0;
- Pi_putColor( c0 & 0xff );
- Pi_putColor( c0 >>8 );
-
- /* 一番最初のパターン */
- /* 上2ラインがみんな同じなので一番長いものは分かっている */
- len = 2;
- while( c0 == Pi_getColor(len) && len<imagemax )
- len += 2;
-
- pos = prepos = 2;
- Pi_putPos( pos );
- Pi_putLen( len/2 );
- off = len;
-
- /* 高速化のため最初の2ラインだけは別に処理する */
- while( off< Width*2 )
- {
- pos = Pi_search( &l, off,prepos, imagemax, Pi_getColor );
-
- if( (l[0] | l[1] | l[2] | l[3] | l[4]) == 0 )
- { Pi_putPos( prepos );
- precol = Pi_getColor( off-1 )& 0xff;
- while(1)
- { c0 = Pi_getColor( off ); off+=2;
- Pi_putColor( c0 & 0xff );
- Pi_putColor( c0 >> 8 );
-
- if ( off > imagemax ) break;
-
- prepos=(-1);
- pos = Pi_search( &l, off,prepos, imagemax, Pi_getColor );
- if( (l[0] | l[1] | l[2] | l[3] | l[4]) )
- break;
- Pi_putBit( 1, 1 );
- }
- Pi_putBit( 0,1 );
- if ( off > imagemax )
- break;
- }
- Pi_putPos( pos );
- Pi_putLen( l[pos] );
- prepos = pos;
- off += l[pos]*2;
- }
- if( head->pix == 8 ) Pi_getColor = Pi_getColor256;
- else Pi_getColor = Pi_getColor16;
-
- while( off< imagemax )
- {
- /* (3)連続している最長パターンを探す */
- pos = Pi_search( &l, off,prepos, imagemax, Pi_getColor );
-
- /* 同じパターンが見つからないとき */
- if( (l[0] | l[1] | l[2] | l[3] | l[4]) == 0 )
- {
- /* (5)前回と同じ位置を記録 */
- Pi_putPos( prepos );
- precol = Pi_getColor( off-1 )& 0xff;
-
- /* (6)2点を記録し注目点移動 */
- while(1)
- { c0 = Pi_getColor( off ); off+=2;
- Pi_putColor( c0 & 0xff );
- Pi_putColor( c0 >> 8 );
-
- if ( off > imagemax )
- break;
-
- /* (7)連続しているパターンがあれば終わり */
- prepos=(-1);
- pos = Pi_search( &l, off,prepos, imagemax, Pi_getColor );
-
- if( (l[0] | l[1] | l[2] | l[3] | l[4]) )
- break;
-
- Pi_putBit( 1, 1 );
- }
- Pi_putBit( 0,1 ); /* 0を書き込む */
- if ( off > imagemax )
- continue;
-
- }
- /* 同じパターンが見つかったとき */
- /* (4')一番長くなる位置と長さを記録 */
- Pi_putPos( pos );
- Pi_putLen( l[pos] );
- prepos = pos;
- off += l[pos]*2;
- }
-
- Pi_putBit( 0, 32 );
-
- return NOERR;
- }
-
- /*********************/
-
- /* 周囲5点から同じパターンを探す */
- int Pi_search( l, off,prepos, imagemax,getColor )
- int *l,off,imagemax,prepos;
- int (*getColor)();
- {
- int i,len,max;
- int bufoff;
-
- max = 0;
- l[0]= 0;
- if( prepos!=0 )
- {
- i = getColor(off-2);
- /* 直前のパターンを比較 */
- if( ((i>>8)& 0x0ff) == (i & 0xff) ) bufoff = off-2;
- else bufoff = off-4;
- len = 0;
- while( getColor(bufoff) == getColor(off+len) )
- { len += 2;
- bufoff += 2;
- if( off+len >= imagemax ) break;
- }
- l[0] = len/2;
- }
-
- /** pos=1~4 **/
- for( i=1; i<5; i++ )
- { if( prepos == i )
- { l[i]=0;
- continue;
- }
- bufoff = off + Pi_posTable[i][0];
- len = 0;
- while( getColor( off+len )==getColor( bufoff ) )
- { len += 2;
- bufoff += 2;
-
- if( off+len >= imagemax ) break;
- }
- l[i] = len/2 ;
- if( l[max] < l[i] ) max = i;
- }
- // for(i=0;i<5;i++) printf("l[%d]=%d,",i,l[i] );printf("\r\n");
-
- return max;
- }
-
- /*********************/
-
- int Pi_getColor256D( off )
- int off;
- {
- if( off < 0 ) return WORD( f2buf+ Width*2 + off );
-
- return WORD( PI_IMAGEBUF + off );
- }
-
- int Pi_getColor16D( off )
- int off;
- {
- if( off < 0 ) return WORD( f2buf+ Width*2 + off );
-
- if( off & 1 )
- { off >>= 1;
- return ((PI_IMAGEBUF[off ] & 0xf0 )>>4)
- | ((PI_IMAGEBUF[off+1] & 0x0f )*256);
- }else
- { off >>= 1;
- return ((PI_IMAGEBUF[off ] & 0x0f ) )
- | ((PI_IMAGEBUF[off ] & 0xf0 )<<4);
- }
- }
-
- int Pi_getColor256( off )
- int off;
- {
- return WORD( PI_IMAGEBUF + off );
- }
-
- int Pi_getColor16( off )
- int off;
- {
- if( off & 1 )
- { off >>= 1;
- return ((PI_IMAGEBUF[off ] & 0xf0 )>>4)
- | ((PI_IMAGEBUF[off+1] & 0x0f )*256);
- }else
- { off >>= 1;
- return ((PI_IMAGEBUF[off ] & 0x0f ) )
- | ((PI_IMAGEBUF[off ] & 0xf0 )<<4);
- }
- }
-
- /*********************/
-
- #define chk_bufpage() \
- if( Pi_countBit >= Pi_maxBit )\
- { if( remallocPixBuf() ) return ERROR;\
- Pi_countBit = 0;\
- }
-
- /* 任意ビット長のデータを格納する */
- int Pi_putBit( dat,bit )
- int dat,bit;
- {
- char restBit[]= { 0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff };
- char usedBit[]= { 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe };
- int rest;
- char *p;
-
- chk_bufpage();
-
- rest = 8-(Pi_countBit & 7);
- while( rest<bit )
- {
- p = &pixel[pixPage][ (Pi_countBit>>3) ];
-
- *p &= usedBit[ (Pi_countBit & 7) ];
- *p |= ((dat>>(bit - rest)) & restBit[rest]);
- bit -= rest;
- Pi_countBit += rest;
- chk_bufpage();
-
- rest = 8-(Pi_countBit & 7);
- }
- if( rest>=bit )
- {
- p = &pixel[pixPage][ (Pi_countBit>>3) ];
-
- *p &= usedBit[ (Pi_countBit & 7) ];
- *p |= ((dat & restBit[bit])<<(rest-bit));
-
- Pi_countBit += bit;
- }
-
- return NOERR;
- }
-
-
- void Pi_putPos( pos )
- int pos;
- {
- switch( pos )
- {
- case 0: Pi_putBit( 0x00, 2 ); break;
- case 1: Pi_putBit( 0x01, 2 ); break;
- case 2: Pi_putBit( 0x02, 2 ); break;
- case 3: Pi_putBit( 0x06, 3 ); break;
- case 4: Pi_putBit( 0x07, 3 ); break;
- }
- }
-
- void Pi_putLen( len )
- unsigned int len;
- {
- unsigned int i;
-
- i=1;
- while( (len>>i) ) i++;
-
- Pi_putBit( 0xfffffffe, i );
- if( i==1 ) return;
-
- Pi_putBit( len, i-1 );
- }
-
- /*************************/
-
- void Pi_initColorTable(col)
- int col;
- {
- int i, j;
-
- for( i=0; i<col; i++ )
- for( j=0; j<col; j++ )
- ColTbl[ j + i*col ] = ((i + col-j) & (col-1));
-
- }
-
- void Pi_putColor16( col )
- int col;
- {
- int i,j,k;
- char *p;
-
- p = ColTbl + precol*16 ;
- j = p[0];
- for( i=1; j!=col ; i++ )
- { k = p[i];
- p[i] = j;
- j = k;
- }
- p[0] = col;
- precol = col;
- i--;
- if( i<2 ) Pi_putBit( 1, 1 ),Pi_putBit( i, 1 );
- else if( i<4 ) Pi_putBit( 0, 2 ),Pi_putBit( i, 1 );
- else if( i<8 ) Pi_putBit( 2, 3 ),Pi_putBit( i, 2 );
- else Pi_putBit( 3, 3 ),Pi_putBit( i, 3 );
-
- }
- void Pi_putColor256( col )
- int col;
- {
- int i,j,k;
- char *p;
-
- p = ColTbl + precol*256 ;
- j = p[0];
- for( i=1; j!=col ; i++ )
- { k = p[i];
- p[i] = j;
- j = k;
- }
- p[0] = col;
- precol = col;
- i--;
- if( i< 2 ) Pi_putBit( 0x01, 1 ),Pi_putBit( i, 1 );
- else if( i< 4 ) Pi_putBit( 0x00, 2 ),Pi_putBit( i, 1 );
- else if( i< 8 ) Pi_putBit( 0x02, 3 ),Pi_putBit( i, 2 );
- else if( i< 16 ) Pi_putBit( 0x06, 4 ),Pi_putBit( i, 3 );
- else if( i< 32 ) Pi_putBit( 0x0e, 5 ),Pi_putBit( i, 4 );
- else if( i< 64 ) Pi_putBit( 0x1e, 6 ),Pi_putBit( i, 5 );
- else if( i<128 ) Pi_putBit( 0x3e, 7 ),Pi_putBit( i, 6 );
- else Pi_putBit( 0x3f, 7 ),Pi_putBit( i, 7 );
-
- }
-
- /********************************************************/
- void freePixBuf()
- {
- int i;
-
- for( i=0; i<=pixPage; i++ )
- PI_FREE( pixel[i] );
- PI_FREE( pixel );
- }
-
- int mallocPixBuf( Width,Height )
- int Width,Height;
- {
- int all,page;
-
- all = Width * Height ; /* 全画面データに必要なメモリ */
- page = (all / pixPageSize )+1 ; /* 最大ページサイズ */
-
- if( (pixel=(char**)PI_MALLOC( sizeof(char*)*page ))==NULL )
- return ERROR;
-
- /* 1ページだけ確保 */
- if( (pixel[0] = (char*)PI_MALLOC( pixPageSize + 2 ))==NULL )
- { free( pixel );
- return ERROR;
- }
-
- return NOERR;
- }
-
- int remallocPixBuf()
- {
- if( (pixel[pixPage+1] = (char*)PI_MALLOC( pixPageSize + 2 ))==NULL )
- { freePixBuf();
- return ERROR;
- }
- pixPage++;
- return NOERR;
- }
-
- /*************************************************************/
- /* 乙女座から得たコメントを分解する */
-
- #define iskanji(c) ( (0x81<=(c) && (c)<=0x9f) || (0xe0<=(c) && (c)<=0xfc))
- #define iskanji2(c) ( (0x40<=(c) && (c)<=0x7e) || (0x80<=(c) && (c)<=0xfc))
-
- int Pi_setComment()
- {
- int i,len;
-
- if( PI_COMMENT==NULL || (len=strlen( PI_COMMENT ))<1 )
- return NOERR;
-
- /* 面倒なのでメモリチェックは無視。これくらいで失敗するかな?? */
-
- for( i=0; i<len ; i++ )
- { if( PI_COMMENT[i]==',' )
- { user=PI_MALLOC( i+1 );
- strncpy( user, PI_COMMENT, i ),user[i]='\0';
-
- for( i++;i<len; i++ )
- if( PI_COMMENT[i]!=' ' && PI_COMMENT[i]!='\t' ) break;
- if( i<len )
- { comment=PI_MALLOC( len-i+2 );
- strcpy( comment, PI_COMMENT+i );
- }
- return NOERR;
- }
- }
- user=PI_MALLOC( len+1 );
- strcpy( user, PI_COMMENT );
-
- return NOERR;
- }
-
- #define ENV_MAX 80
-
- char *my_getenv( name )
- char *name;
- {
- char envbuf[ ENV_MAX+1 ];
- int i;
-
- /* '='で始まって末尾に '\\' を追加したものが返される */
- if( (i=TOS_getPath( envbuf, name, strlen(name) ))==0 )
- return NULL;
-
- if( i>2 )
- { if( !iskanji( envbuf[i-2] ) ) /* 漢字コード2バイト目でない */
- envbuf[i-1] = '\0';
- }
- else if( i>0 )
- envbuf[i-1] = '\0';
-
- if( i<1 || (user = PI_MALLOC( strlen( &envbuf[1] )+1 ))==NULL )
- return '\0';
-
- strcpy( user, &envbuf[1] ); /* '=' のぶんスキップ */
-
- return user;
- }
-
- /********************************************************/
-
- int Pi_writeBuffers( fp,head,palette )
- FILE *fp;
- PiHeader *head;
- char *palette;
- {
- int i;
- char *p;
-
- /****/
- if( 2 != fwrite( "Pi", 1,2, fp ) )
- return ERROR;
-
- p = '\0';
- if( user != '\0' ) p = user;
- else p = my_getenv("USER");
- if( p != '\0' )
- { fwrite( "User:", 1,5, fp );
- fwrite( p, 1, strlen(p), fp );
- }
- if( comment == '\0' ) p = def_comment;
- else p = comment;
- fwrite( "\r\n", 1, 2, fp);
- fwrite( p, 1, strlen(p), fp);
- fwrite( "\x1a\0", 1, 2, fp);
-
- /****/
- fwrite( head, 1, 4, fp );
- fwrite( head->name, 1, 4, fp );
- fputc ( head->mdat_len>>8 , fp );
- fputc ( head->mdat_len , fp );
- if( head->mdat_len>0 ) fwrite( head->mdat, 1, head->mdat_len, fp );
- fputc ( head->x >>8 , fp );
- fputc ( head->x , fp );
- fputc ( head->y >>8 , fp );
- fputc ( head->y , fp );
-
- fwrite( palette, 1, (1<<head->pix)*3 ,fp);
-
- /****/
- for( i=0; i<pixPage; i++ )
- if( pixPageSize != fwrite( &pixel[i][0], 1, pixPageSize, fp ) )
- return ERROR;
- if( (i = ((Pi_countBit+7)>>3)) >0 )
- if( i != fwrite( &pixel[pixPage][0], 1, i, fp ) )
- return ERROR;
-
-
- return NOERR;
- }
-
- void Pi_head( head,palette,size,pal )
- char *palette;
- PiHeader *head;
- POINT *size;
- char *pal;
- {
- int i,j,col;
-
- head->mode = 0;
- head->n = 1;
- head->m = 1;
- head->pix = pi_imge->pix;
-
- strncpy( head->name, "TOWN",4 );
-
- head->mdat_len = 0;
- head->x = (size->x+31)& 0xffe0 ; /* う~む。仕方がない。*/
- head->y = size->y;
-
- /*** パレットデータ ***/
-
- col = (1 << head->pix);
- for( i=0,j=8; i<col; i++,j+=8 )
- {
- palette[ i*3 ] = pal[ j+1 ] ; /* R */
- palette[ i*3+1 ] = pal[ j+2 ] ; /* G */
- palette[ i*3+2 ] = pal[ j ] ; /* B */
- }
-
- }
-
- int Pi_save( fp, buf, size, pix, pal )
- FILE *fp;
- char *buf,*pal;
- int pix;
- POINT *size;
- {
- PiHeader head;
- int col,ret;
- char *palette;
-
- if( pix ==8 ) col = 256;
- else col = 16;
-
- if( (palette=(char*)PI_MALLOC( col*3 + col*col ))==NULL )
- return PI_ERROR_NO_MEMORY;
- ColTbl = palette + col*3 ;
-
- if( mallocPixBuf( PI_SIZE_X,PI_SIZE_Y ) )
- { PI_FREE(palette);
- return PI_ERROR_NO_MEMORY;
- }
-
- /*** ヘッダ作成 ***/
- Pi_head( &head, palette, &PI_SIZE, PI_COLMAP );
-
- /*** 圧縮 ***/
- Pi_initColorTable( col );
- ret=Pi_encode( &head, buf );
- ret = 0;
-
- /*** 書き出し ***/
- if( ret==NOERR )
- ret=Pi_writeBuffers( fp, &head, palette );
-
-
- PI_FREE( palette );
- freePixBuf();
-
- return ret;
- }
-
- /*******************************************************************/
- /** プラグイン呼び出し **/
-
- int APL_exec()
- {
- FILE *fp;
- int ret;
-
- if( PI_PIX >8 ) return ERROR;
-
- Pi_setComment();
-
- if( (fp = fopen( PI_FNAME , "wb" )) == NULL )
- return PI_ERROR_FILE_OPEN;
-
- ret=Pi_save( fp, PI_IMAGEBUF, &PI_SIZE, PI_PIX, PI_COLMAP );
- fclose( fp );
- if( ret ) remove( PI_FNAME );
-
- if( user != '\0' ) PI_FREE( user );
- if( comment != '\0' ) PI_FREE( comment );
- return ret;
- }
-
-